package krao.parser;

import krao.data.TBox;

import org.apache.log4j.Logger;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.StmtIterator;

public class TBoxParser {
	private final static Logger logger = Logger.getLogger(TBoxParser.class);

	public static TBox getTbox(OntModel om) {
		TBox tbox = new TBox();
		TBoxParser.getClasses(om, tbox);
		TBoxParser.getProperties(om, tbox);
		return tbox;
	}

	private static void getClasses(OntModel om, TBox tbox) {
		Property typeProperty = ResourceFactory
				.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
		Resource classResource = ResourceFactory
				.createResource("http://www.w3.org/2002/07/owl#Class");
		Property subclassProperty = ResourceFactory
				.createProperty("http://www.w3.org/2000/01/rdf-schema#subClassOf");

		StmtIterator si = om.listStatements(null, typeProperty, classResource);
		while (si.hasNext()) {
			Resource subject = si.next().getSubject();
			String className = subject.getLocalName();
			logger.debug(className);
			// add this class to tbox
			tbox.addClass(className);
			// find out if it is subclass of some other class
			StmtIterator subclassOf = om.listStatements(subject, subclassProperty,
					(Resource) null);
			while (subclassOf.hasNext()) {
				Resource tmp = subclassOf.next().getObject().as(Resource.class);
				tbox.addSuperClass(className, tmp.getLocalName());
			}
		}
	}

	private static void getProperties(OntModel om, TBox tbox) {
		Property typeProperty = ResourceFactory
				.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
		Resource objectPropertyResource = ResourceFactory
				.createProperty("http://www.w3.org/2002/07/owl#ObjectProperty");
		Property rangeProperty = ResourceFactory
				.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#range");
		Property domainProperty = ResourceFactory
				.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#domain");
		Property subpropertyProperty = ResourceFactory
				.createProperty("http://www.w3.org/2000/01/rdf-schema#subPropertyOf");
		Property inverseProperty = ResourceFactory
				.createProperty("http://www.w3.org/2002/07/owl#inverseOf");

		StmtIterator si = om.listStatements(null, typeProperty, objectPropertyResource);

		while (si.hasNext()) {
			Resource subject = si.next().getSubject();
			String propName = subject.getLocalName();
			logger.debug(propName);
			tbox.addProperty(propName);

			StmtIterator domains = om.listStatements(subject, domainProperty,
					(Resource) null);
			while (domains.hasNext()) {
				Resource tmp = domains.next().getObject().as(Resource.class);
				tbox.addDomain(propName, tmp.getLocalName());
			}

			StmtIterator ranges = om.listStatements(subject, rangeProperty,
					(Resource) null);
			while (ranges.hasNext()) {
				Resource tmp = ranges.next().getObject().as(Resource.class);
				tbox.addRange(propName, tmp.getLocalName());
			}

			StmtIterator subproperties = om.listStatements(subject, subpropertyProperty,
					(Resource) null);
			while (subproperties.hasNext()) {
				Resource tmp = subproperties.next().getObject().as(Resource.class);
				tbox.addSuperProperty(propName, tmp.getLocalName());
			}

			StmtIterator invproperties = om.listStatements(subject, inverseProperty,
					(Resource) null);
			while (invproperties.hasNext()) {
				Resource tmp = invproperties.next().getObject().as(Resource.class);
				tbox.addInverseProperty(propName, tmp.getLocalName());
			}
		}
	}
}

/**
 * Old code - this is approx. the way to get ABox if it is included in same file
 * as the TBox
 * 
 * private static void getABox(OntModel om, TBox tbox, ABox abox) { Property
 * typeProperty = ResourceFactory
 * .createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
 * 
 * // find all class assertions StmtIterator si = om.listStatements(null,
 * typeProperty, (Resource) null); while (si.hasNext()) { String object =
 * si.next().getObject().as(Resource.class).getLocalName(); String subject =
 * si.next().getSubject().getLocalName(); // if there is some class in tbox if
 * (tbox.containsClass(subject)) { logger.info(String.format("%s a %s", object,
 * subject)); // add this class to abox abox.addClassAssertion(object, subject);
 * } }
 * 
 * // find all property assertions for (TBoxProperty oneProp : tbox.properties)
 * { Property thisProperty = ResourceFactory.createProperty(":" +
 * oneProp.getName()); // find all class assertions si = om.listStatements(null,
 * thisProperty, (Resource) null); while (si.hasNext()) { String object =
 * si.next().getObject().as(Resource.class).getLocalName(); String subject =
 * si.next().getSubject().getLocalName(); // if there is some class in tbox //
 * if (tbox.containsClass(subject)) { logger.debug(String.format("%s %s %s",
 * object, oneProp.getName(), subject)); // add this class to abox
 * abox.addPropertyAssertion(object, oneProp.getName(), subject); } } }
 */
